/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package grex.Data;

import grex.WekaModels.WekaPredictiveModel;
import grex.ErrorManagement.ErrorManager;
import grex.IPredictiveModel;
import grex.WekaModels.GrexJ48Bag;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author RIK
 */
public class ExtractionArffTableModel extends ArffTableModel {

    IPredictiveModel opaqueModel;
    private Hashtable<String, double[][]> extractionTrainFolds = new Hashtable<String, double[][]>();
    private Hashtable<String, double[][]> extractionValFolds = new Hashtable<String, double[][]>();
    private Hashtable<String, double[][]> extractionTestFolds = new Hashtable<String, double[][]>();
    private boolean useOracle = false;
    ArffTableModel orgData;
    HashMap<String,IPredictiveModel> opaqueModels = new HashMap();
    public ExtractionArffTableModel(ArffTableModel data, IPredictiveModel model) {
        super(data);
        this.opaqueModel = model;
        orgData=data;
    }

    /*
     * public double[][] getTestFold(String fold) {
     *
     *
     * }
     *
     * public double[][] getValFold(String fold) {
     *
     * return data; }
     */
    //Should always be used to get a fold as lazy initzilation is used.
    public IPredictiveModel getModel(){
        return opaqueModel;
    }
    
    public IPredictiveModel getModel(String fold){
        return opaqueModels.get(fold);
    }
    
    public void setUseOracle(boolean useOracle) {
        this.useOracle = useOracle;
    }

    @Override
    public synchronized double[][] getTrainFold(String fold) {                        
        double[][] extData = extractionTrainFolds.get(fold);
        if (extData == null) {
            
            
            
            
            
            double[][] data = super.getTrainFold(fold);
            extData = new double[data.length][data[0].length];
            
            
            opaqueModel = new GrexJ48Bag(orgData);
            opaqueModels.put(fold, opaqueModel);
            
            
            
            opaqueModel.initFold(fold);
            opaqueModel.train();
            PredictionContainer pc = opaqueModel.getPcTrain();
           
            for (int i = 0; i < data.length; i++) {
                extData[i] = Arrays.copyOfRange(data[i], 0, data[i].length);
                Prediction p = pc.get(data[i]);
                extData[i][extData[i].length - 1] = p.getPrediction();
            }
            
            
            if (useOracle) {
                double[][] testData = super.getTestFold(fold);
                double[][] oracleData = new double[extData.length+testData.length][testData[0].length];
                for(int i = 0 ; i<extData.length;i++)
                    oracleData[i] = extData[i];
                opaqueModel.execute(opaqueModel.getPcTest());
                pc = opaqueModel.getPcTest();
                for (int i = 0; i < testData.length; i++) {
                    int oI = extData.length + i; 
                    oracleData[oI] = Arrays.copyOfRange(testData[i], 0, testData[i].length);
                    Prediction p = pc.get(testData[i]);
                    oracleData[oI][oracleData[oI].length - 1] = p.getPrediction();
                }
                extData = oracleData;
            }

            extractionTrainFolds.put(fold, extData);
        }
        return extData;
    }    
}
